home *** CD-ROM | disk | FTP | other *** search
/ Aminet 45 / Aminet 45 (2001)(GTI - Schatztruhe)[!][Oct 2001].iso / Aminet / gfx / x11 / x3270_3_2_16.lha / amiga_src / ansi.c < prev    next >
C/C++ Source or Header  |  2001-06-23  |  36KB  |  1,516 lines

  1. /*
  2.  * Copyright 1993, 1994, 1995, 1996, 1999, 2000 by Paul Mattes.
  3.  *  Permission to use, copy, modify, and distribute this software and its
  4.  *  documentation for any purpose and without fee is hereby granted,
  5.  *  provided that the above copyright notice appear in all copies and that
  6.  *  both that copyright notice and this permission notice appear in
  7.  *  supporting documentation.
  8.  */
  9.  
  10. /*
  11.  *    ansi.c
  12.  *        ANSI terminal emulation.
  13.  */
  14.  
  15. #include "globals.h"
  16.  
  17. #if defined(X3270_ANSI) /*[*/
  18.  
  19. #if defined(X3270_DISPLAY) /*[*/
  20. #include <X11/Shell.h>
  21. #endif /*]*/
  22.  
  23. #include "appres.h"
  24. #include "ctlr.h"
  25.  
  26. #include "ansic.h"
  27. #include "ctlrc.h"
  28. #include "hostc.h"
  29. #include "screenc.h"
  30. #include "scrollc.h"
  31. #include "tablesc.h"
  32. #include "telnetc.h"
  33. #include "trace_dsc.h"
  34.  
  35. #define    SC    1    /* save cursor position */
  36. #define RC    2    /* restore cursor position */
  37. #define NL    3    /* new line */
  38. #define UP    4    /* cursor up */
  39. #define    E2    5    /* second level of ESC processing */
  40. #define rS    6    /* reset */
  41. #define IC    7    /* insert chars */
  42. #define DN    8    /* cursor down */
  43. #define RT    9    /* cursor right */
  44. #define LT    10    /* cursor left */
  45. #define CM    11    /* cursor motion */
  46. #define ED    12    /* erase in display */
  47. #define EL    13    /* erase in line */
  48. #define IL    14    /* insert lines */
  49. #define DL    15    /* delete lines */
  50. #define DC    16    /* delete characters */
  51. #define    SG    17    /* set graphic rendition */
  52. #define BL    18    /* ring bell */
  53. #define NP    19    /* new page */
  54. #define BS    20    /* backspace */
  55. #define CR    21    /* carriage return */
  56. #define LF    22    /* line feed */
  57. #define HT    23    /* horizontal tab */
  58. #define E1    24    /* first level of ESC processing */
  59. #define Xx    25    /* undefined control character (nop) */
  60. #define Pc    26    /* printing character */
  61. #define Sc    27    /* semicolon (after ESC [) */
  62. #define Dg    28    /* digit (after ESC [ or ESC [ ?) */
  63. #define RI    29    /* reverse index */
  64. #define DA    30    /* send device attributes */
  65. #define SM    31    /* set mode */
  66. #define RM    32    /* reset mode */
  67. #define DO    33    /* return terminal ID (obsolete) */
  68. #define SR    34    /* device status report */
  69. #define CS    35    /* character set designate */
  70. #define E3    36    /* third level of ESC processing */
  71. #define DS    37    /* DEC private set */
  72. #define DR    38    /* DEC private reset */
  73. #define DV    39    /* DEC private save */
  74. #define DT    40    /* DEC private restore */
  75. #define SS    41    /* set scrolling region */
  76. #define TM    42    /* text mode (ESC ]) */
  77. #define T2    43    /* semicolon (after ESC ]) */
  78. #define TX    44    /* text parameter (after ESC ] n ;) */
  79. #define TB    45    /* text parameter done (ESC ] n ; xxx BEL) */
  80. #define TS    46    /* tab set */
  81. #define TC    47    /* tab clear */
  82. #define C2    48    /* character set designate (finish) */
  83. #define G0    49    /* select G0 character set */
  84. #define G1    50    /* select G1 character set */
  85. #define G2    51    /* select G2 character set */
  86. #define G3    52    /* select G3 character set */
  87. #define S2    53    /* select G2 for next character */
  88. #define S3    54    /* select G3 for next character */
  89.  
  90. #ifdef AMIGA
  91. #define TEXT Text3270
  92. #endif
  93.  
  94. static enum state {
  95.     DATA = 0, ESC = 1, CSDES = 2,
  96.     N1 = 3, DECP = 4, TEXT = 5, TEXT2 = 6
  97. } state = DATA;
  98.  
  99. static enum state ansi_data_mode(int, int);
  100. static enum state dec_save_cursor(int, int);
  101. static enum state dec_restore_cursor(int, int);
  102. static enum state ansi_newline(int, int);
  103. static enum state ansi_cursor_up(int, int);
  104. static enum state ansi_esc2(int, int);
  105. static enum state ansi_reset(int, int);
  106. static enum state ansi_insert_chars(int, int);
  107. static enum state ansi_cursor_down(int, int);
  108. static enum state ansi_cursor_right(int, int);
  109. static enum state ansi_cursor_left(int, int);
  110. static enum state ansi_cursor_motion(int, int);
  111. static enum state ansi_erase_in_display(int, int);
  112. static enum state ansi_erase_in_line(int, int);
  113. static enum state ansi_insert_lines(int, int);
  114. static enum state ansi_delete_lines(int, int);
  115. static enum state ansi_delete_chars(int, int);
  116. static enum state ansi_sgr(int, int);
  117. static enum state ansi_bell(int, int);
  118. static enum state ansi_newpage(int, int);
  119. static enum state ansi_backspace(int, int);
  120. static enum state ansi_cr(int, int);
  121. static enum state ansi_lf(int, int);
  122. static enum state ansi_htab(int, int);
  123. static enum state ansi_escape(int, int);
  124. static enum state ansi_nop(int, int);
  125. static enum state ansi_printing(int, int);
  126. static enum state ansi_semicolon(int, int);
  127. static enum state ansi_digit(int, int);
  128. static enum state ansi_reverse_index(int, int);
  129. static enum state ansi_send_attributes(int, int);
  130. static enum state ansi_set_mode(int, int);
  131. static enum state ansi_reset_mode(int, int);
  132. static enum state dec_return_terminal_id(int, int);
  133. static enum state ansi_status_report(int, int);
  134. static enum state ansi_cs_designate(int, int);
  135. static enum state ansi_esc3(int, int);
  136. static enum state dec_set(int, int);
  137. static enum state dec_reset(int, int);
  138. static enum state dec_save(int, int);
  139. static enum state dec_restore(int, int);
  140. static enum state dec_scrolling_region(int, int);
  141. static enum state xterm_text_mode(int, int);
  142. static enum state xterm_text_semicolon(int, int);
  143. static enum state xterm_text(int, int);
  144. static enum state xterm_text_do(int, int);
  145. static enum state ansi_htab_set(int, int);
  146. static enum state ansi_htab_clear(int, int);
  147. static enum state ansi_cs_designate2(int, int);
  148. static enum state ansi_select_g0(int, int);
  149. static enum state ansi_select_g1(int, int);
  150. static enum state ansi_select_g2(int, int);
  151. static enum state ansi_select_g3(int, int);
  152. static enum state ansi_one_g2(int, int);
  153. static enum state ansi_one_g3(int, int);
  154.  
  155. static enum state (*ansi_fn[])(int, int) = {
  156. /* 0 */        ansi_data_mode,
  157. /* 1 */        dec_save_cursor,
  158. /* 2 */        dec_restore_cursor,
  159. /* 3 */        ansi_newline,
  160. /* 4 */        ansi_cursor_up,
  161. /* 5 */        ansi_esc2,
  162. /* 6 */        ansi_reset,
  163. /* 7 */        ansi_insert_chars,
  164. /* 8 */        ansi_cursor_down,
  165. /* 9 */        ansi_cursor_right,
  166. /* 10 */    ansi_cursor_left,
  167. /* 11 */    ansi_cursor_motion,
  168. /* 12 */    ansi_erase_in_display,
  169. /* 13 */    ansi_erase_in_line,
  170. /* 14 */    ansi_insert_lines,
  171. /* 15 */    ansi_delete_lines,
  172. /* 16 */    ansi_delete_chars,
  173. /* 17 */    ansi_sgr,
  174. /* 18 */    ansi_bell,
  175. /* 19 */    ansi_newpage,
  176. /* 20 */    ansi_backspace,
  177. /* 21 */    ansi_cr,
  178. /* 22 */    ansi_lf,
  179. /* 23 */    ansi_htab,
  180. /* 24 */    ansi_escape,
  181. /* 25 */    ansi_nop,
  182. /* 26 */    ansi_printing,
  183. /* 27 */    ansi_semicolon,
  184. /* 28 */    ansi_digit,
  185. /* 29 */    ansi_reverse_index,
  186. /* 30 */    ansi_send_attributes,
  187. /* 31 */    ansi_set_mode,
  188. /* 32 */    ansi_reset_mode,
  189. /* 33 */    dec_return_terminal_id,
  190. /* 34 */    ansi_status_report,
  191. /* 35 */    ansi_cs_designate,
  192. /* 36 */    ansi_esc3,
  193. /* 37 */    dec_set,
  194. /* 38 */    dec_reset,
  195. /* 39 */    dec_save,
  196. /* 40 */    dec_restore,
  197. /* 41 */    dec_scrolling_region,
  198. /* 42 */    xterm_text_mode,
  199. /* 43 */    xterm_text_semicolon,
  200. /* 44 */    xterm_text,
  201. /* 45 */    xterm_text_do,
  202. /* 46 */    ansi_htab_set,
  203. /* 47 */    ansi_htab_clear,
  204. /* 48 */    ansi_cs_designate2,
  205. /* 49 */    ansi_select_g0,
  206. /* 50 */    ansi_select_g1,
  207. /* 51 */    ansi_select_g2,
  208. /* 52 */    ansi_select_g3,
  209. /* 53 */    ansi_one_g2,
  210. /* 54 */    ansi_one_g3,
  211. };
  212.  
  213. static unsigned char st[7][256] = {
  214. /*
  215.  * State table for base processing (state == DATA)
  216.  */
  217. {
  218.          /* 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  */
  219. /* 00 */       Xx,Xx,Xx,Xx,Xx,Xx,Xx,BL,BS,HT,LF,LF,NP,CR,G1,G0,
  220. /* 10 */       Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,E1,Xx,Xx,Xx,Xx,
  221. /* 20 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  222. /* 30 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  223. /* 40 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  224. /* 50 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  225. /* 60 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  226. /* 70 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Xx,
  227. /* 80 */       Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,
  228. /* 90 */       Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,Xx,
  229. /* a0 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  230. /* b0 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  231. /* c0 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  232. /* d0 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  233. /* e0 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,
  234. /* f0 */       Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc,Pc
  235. },
  236.  
  237. /*
  238.  * State table for ESC processing (state == ESC)
  239.  */
  240. {
  241.          /* 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  */
  242. /* 00 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  243. /* 10 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  244. /* 20 */    0, 0, 0, 0, 0, 0, 0, 0,CS,CS,CS,CS, 0, 0, 0, 0,
  245. /* 30 */    0, 0, 0, 0, 0, 0, 0,SC,RC, 0, 0, 0, 0, 0, 0, 0,
  246. /* 40 */    0, 0, 0, 0, 0,NL, 0, 0,TS, 0, 0, 0, 0,RI,S2,S3,
  247. /* 50 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,E2, 0,TM, 0, 0,
  248. /* 60 */    0, 0, 0,rS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,G2,G3,
  249. /* 70 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  250. /* 80 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  251. /* 90 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  252. /* a0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  253. /* b0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  254. /* c0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  255. /* d0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  256. /* e0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  257. /* f0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  258. },
  259.  
  260. /*
  261.  * State table for ESC ()*+ C processing (state == CSDES)
  262.  */
  263. {
  264.          /* 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  */
  265. /* 00 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  266. /* 10 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  267. /* 20 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  268. /* 30 */       C2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  269. /* 40 */    0,C2,C2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  270. /* 50 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  271. /* 60 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  272. /* 70 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  273. /* 80 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  274. /* 90 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  275. /* a0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  276. /* b0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  277. /* c0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  278. /* d0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  279. /* e0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  280. /* f0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  281. },
  282.  
  283. /*
  284.  * State table for ESC [ processing (state == N1)
  285.  */
  286. {
  287.          /* 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  */
  288. /* 00 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  289. /* 10 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  290. /* 20 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  291. /* 30 */       Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg, 0,Sc, 0, 0, 0,E3,
  292. /* 40 */       IC,UP,DN,RT,LT, 0, 0, 0,CM, 0,ED,EL,IL,DL, 0, 0,
  293. /* 50 */       DC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  294. /* 60 */    0, 0, 0,DA, 0, 0,CM,TC,SM, 0, 0, 0,RM,SG,SR, 0,
  295. /* 70 */    0, 0,SS, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  296. /* 80 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  297. /* 90 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  298. /* a0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  299. /* b0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  300. /* c0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  301. /* d0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  302. /* e0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  303. /* f0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  304. },
  305.  
  306. /*
  307.  * State table for ESC [ ? processing (state == DECP)
  308.  */
  309. {
  310.          /* 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  */
  311. /* 00 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  312. /* 10 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  313. /* 20 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  314. /* 30 */       Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg, 0, 0, 0, 0, 0, 0,
  315. /* 40 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  316. /* 50 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  317. /* 60 */    0, 0, 0, 0, 0, 0, 0, 0,DS, 0, 0, 0,DR, 0, 0, 0,
  318. /* 70 */    0, 0,DT,DV, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  319. /* 80 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  320. /* 90 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  321. /* a0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  322. /* b0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  323. /* c0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  324. /* d0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  325. /* e0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  326. /* f0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  327. },
  328.  
  329. /*
  330.  * State table for ESC ] processing (state == TEXT)
  331.  */
  332. {
  333.          /* 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  */
  334. /* 00 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  335. /* 10 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  336. /* 20 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  337. /* 30 */       Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg,Dg, 0,T2, 0, 0, 0, 0,
  338. /* 40 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  339. /* 50 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  340. /* 60 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  341. /* 70 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  342. /* 80 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  343. /* 90 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  344. /* a0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  345. /* b0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  346. /* c0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  347. /* d0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  348. /* e0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  349. /* f0 */    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  350. },
  351.  
  352. /*
  353.  * State table for ESC ] n ; processing (state == TEXT2)
  354.  */
  355. {
  356.          /* 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f  */
  357. /* 00 */        0, 0, 0, 0, 0, 0, 0,TB, 0, 0, 0, 0, 0, 0, 0, 0,
  358. /* 10 */        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  359. /* 20 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  360. /* 30 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  361. /* 40 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  362. /* 50 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  363. /* 60 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  364. /* 70 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,Xx,
  365. /* 80 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  366. /* 90 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  367. /* a0 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  368. /* b0 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  369. /* c0 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  370. /* d0 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  371. /* e0 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,
  372. /* f0 */       TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX,TX
  373. },
  374. };
  375.  
  376. /* Character sets. */
  377. #define CS_G0        0
  378. #define CS_G1        1
  379. #define CS_G2        2
  380. #define CS_G3        3
  381.  
  382. /* Character set designations. */
  383. #define CSD_LD        0
  384. #define CSD_UK        1
  385. #define CSD_US        2
  386.  
  387. static int      saved_cursor = 0;
  388. #define NN    20
  389. static int      n[NN], nx = 0;
  390. #define NT    256
  391. static char     text[NT + 1];
  392. static int      tx = 0;
  393. static int      ansi_ch;
  394. static unsigned char gr = 0;
  395. static unsigned char saved_gr = 0;
  396. static unsigned char fg = 0;
  397. static unsigned char saved_fg = 0;
  398. static unsigned char bg = 0;
  399. static unsigned char saved_bg = 0;
  400. static int    cset = CS_G0;
  401. static int    saved_cset = CS_G0;
  402. static int    csd[4] = { CSD_US, CSD_US, CSD_US, CSD_US };
  403. static int    saved_csd[4] = { CSD_US, CSD_US, CSD_US, CSD_US };
  404. static int    once_cset = -1;
  405. static int      insert_mode = 0;
  406. static int      auto_newline_mode = 0;
  407. static int      appl_cursor = 0;
  408. static int      saved_appl_cursor = 0;
  409. static int      wraparound_mode = 1;
  410. static int      saved_wraparound_mode = 1;
  411. static int      rev_wraparound_mode = 0;
  412. static int      saved_rev_wraparound_mode = 0;
  413. static Boolean  saved_altbuffer = False;
  414. static int      scroll_top = -1;
  415. static int      scroll_bottom = -1;
  416. static unsigned char *tabs = (unsigned char *) NULL;
  417. static char    gnnames[] = "()*+";
  418. static char    csnames[] = "0AB";
  419. static int    cs_to_change;
  420.  
  421. static Boolean  held_wrap = False;
  422.  
  423. static void    ansi_scroll(void);
  424.  
  425. static enum state
  426. ansi_data_mode(int ig1 unused, int ig2 unused)
  427. {
  428.     return DATA;
  429. }
  430.  
  431. static enum state
  432. dec_save_cursor(int ig1 unused, int ig2 unused)
  433. {
  434.     int i;
  435.  
  436.     saved_cursor = cursor_addr;
  437.     saved_cset = cset;
  438.     for (i = 0; i < 4; i++)
  439.         saved_csd[i] = csd[i];
  440.     saved_fg = fg;
  441.     saved_bg = bg;
  442.     saved_gr = gr;
  443.     return DATA;
  444. }
  445.  
  446. static enum state
  447. dec_restore_cursor(int ig1 unused, int ig2 unused)
  448. {
  449.     int i;
  450.  
  451.     cset = saved_cset;
  452.     for (i = 0; i < 4; i++)
  453.         csd[i] = saved_csd[i];
  454.     fg = saved_fg;
  455.     bg = saved_bg;
  456.     gr = saved_gr;
  457.     cursor_move(saved_cursor);
  458.     held_wrap = False;
  459.     return DATA;
  460. }
  461.  
  462. static enum state
  463. ansi_newline(int ig1 unused, int ig2 unused)
  464. {
  465.     int nc;
  466.  
  467.     cursor_move(cursor_addr - (cursor_addr % COLS));
  468.     nc = cursor_addr + COLS;
  469.     if (nc < scroll_bottom * COLS)
  470.         cursor_move(nc);
  471.     else
  472.         ansi_scroll();
  473.     held_wrap = False;
  474.     return DATA;
  475. }
  476.  
  477. static enum state
  478. ansi_cursor_up(int nn, int ig2 unused)
  479. {
  480.     int rr;
  481.  
  482.     if (nn < 1)
  483.         nn = 1;
  484.     rr = cursor_addr / COLS;
  485.     if (rr - nn < 0)
  486.         cursor_move(cursor_addr % COLS);
  487.     else
  488.         cursor_move(cursor_addr - (nn * COLS));
  489.     held_wrap = False;
  490.     return DATA;
  491. }
  492.  
  493. static enum state
  494. ansi_esc2(int ig1 unused, int ig2 unused)
  495. {
  496.     register int    i;
  497.  
  498.     for (i = 0; i < NN; i++)
  499.         n[i] = 0;
  500.     nx = 0;
  501.     return N1;
  502. }
  503.  
  504. static enum state
  505. ansi_reset(int ig1 unused, int ig2 unused)
  506. {
  507.     int i;
  508.     static Boolean first = True;
  509.  
  510.     gr = 0;
  511.     saved_gr = 0;
  512.     fg = 0;
  513.     saved_fg = 0;
  514.     bg = 0;
  515.     saved_bg = 0;
  516.     cset = CS_G0;
  517.     saved_cset = CS_G0;
  518.     csd[0] = csd[1] = csd[2] = csd[3] = CSD_US;
  519.     saved_csd[0] = saved_csd[1] = saved_csd[2] = saved_csd[3] = CSD_US;
  520.     once_cset = -1;
  521.     saved_cursor = 0;
  522.     insert_mode = 0;
  523.     auto_newline_mode = 0;
  524.     appl_cursor = 0;
  525.     saved_appl_cursor = 0;
  526.     wraparound_mode = 1;
  527.     saved_wraparound_mode = 1;
  528.     rev_wraparound_mode = 0;
  529.     saved_rev_wraparound_mode = 0;
  530.     saved_altbuffer = False;
  531.     scroll_top = 1;
  532.     scroll_bottom = ROWS;
  533.     if (tabs == (unsigned char *)NULL)
  534.         Free((char *)tabs);
  535.     tabs = (unsigned char *)Malloc((COLS+7)/8);
  536.     for (i = 0; i < (COLS+7)/8; i++)
  537.         tabs[i] = 0x01;
  538.     held_wrap = False;
  539.     if (!first) {
  540.         ctlr_altbuffer(True);
  541.         ctlr_aclear(0, ROWS * COLS, 1);
  542.         ctlr_altbuffer(False);
  543.         ctlr_clear(False);
  544.     }
  545.     first = False;
  546.     return DATA;
  547. }
  548.  
  549. static enum state
  550. ansi_insert_chars(int nn, int ig2 unused)
  551. {
  552.     int cc = cursor_addr % COLS;    /* current col */
  553.     int mc = COLS - cc;        /* max chars that can be inserted */
  554.     int ns;                /* chars that are shifting */
  555.  
  556.     if (nn < 1)
  557.         nn = 1;
  558.     if (nn > mc)
  559.         nn = mc;
  560.  
  561.     /* Move the surviving chars right */
  562.     ns = mc - nn;
  563.     if (ns)
  564.         ctlr_bcopy(cursor_addr, cursor_addr + nn, ns, 1);
  565.  
  566.     /* Clear the middle of the line */
  567.     ctlr_aclear(cursor_addr, nn, 1);
  568.     return DATA;
  569. }
  570.  
  571. static enum state
  572. ansi_cursor_down(int nn, int ig2 unused)
  573. {
  574.     int rr;
  575.  
  576.     if (nn < 1)
  577.         nn = 1;
  578.     rr = cursor_addr / COLS;
  579.     if (rr + nn >= ROWS)
  580.         cursor_move((ROWS-1)*COLS + (cursor_addr%COLS));
  581.     else
  582.         cursor_move(cursor_addr + (nn * COLS));
  583.     held_wrap = False;
  584.     return DATA;
  585. }
  586.  
  587. static enum state
  588. ansi_cursor_right(int nn, int ig2 unused)
  589. {
  590.     int cc;
  591.  
  592.     if (nn < 1)
  593.         nn = 1;
  594.     cc = cursor_addr % COLS;
  595.     if (cc == COLS-1)
  596.         return DATA;
  597.     if (cc + nn >= COLS)
  598.         nn = COLS - 1 - cc;
  599.     cursor_move(cursor_addr + nn);
  600.     held_wrap = False;
  601.     return DATA;
  602. }
  603.  
  604. static enum state
  605. ansi_cursor_left(int nn, int ig2 unused)
  606. {
  607.     int cc;
  608.  
  609.     if (held_wrap) {
  610.         held_wrap = False;
  611.         return DATA;
  612.     }
  613.     if (nn < 1)
  614.         nn = 1;
  615.     cc = cursor_addr % COLS;
  616.     if (!cc)
  617.         return DATA;
  618.     if (nn > cc)
  619.         nn = cc;
  620.     cursor_move(cursor_addr - nn);
  621.     return DATA;
  622. }
  623.  
  624. static enum state
  625. ansi_cursor_motion(int n1, int n2)
  626. {
  627.     if (n1 < 1) n1 = 1;
  628.     if (n1 > ROWS) n1 = ROWS;
  629.     if (n2 < 1) n2 = 1;
  630.     if (n2 > COLS) n2 = COLS;
  631.     cursor_move((n1 - 1) * COLS + (n2 - 1));
  632.     held_wrap = False;
  633.     return DATA;
  634. }
  635.  
  636. static enum state
  637. ansi_erase_in_display(int nn, int ig2 unused)
  638. {
  639.     switch (nn) {
  640.         case 0:    /* below */
  641.         ctlr_aclear(cursor_addr, (ROWS * COLS) - cursor_addr, 1);
  642.         break;
  643.         case 1:    /* above */
  644.         ctlr_aclear(0, cursor_addr + 1, 1);
  645.         break;
  646.         case 2:    /* all (without moving cursor) */
  647.         if (cursor_addr == 0 && !is_altbuffer)
  648.             scroll_save(ROWS, True);
  649.         ctlr_aclear(0, ROWS * COLS, 1);
  650.         break;
  651.     }
  652.     return DATA;
  653. }
  654.  
  655. static enum state
  656. ansi_erase_in_line(int nn, int ig2 unused)
  657. {
  658.     int nc = cursor_addr % COLS;
  659.  
  660.     switch (nn) {
  661.         case 0:    /* to right */
  662.         ctlr_aclear(cursor_addr, COLS - nc, 1);
  663.         break;
  664.         case 1:    /* to left */
  665.         ctlr_aclear(cursor_addr - nc, nc+1, 1);
  666.         break;
  667.         case 2:    /* all */
  668.         ctlr_aclear(cursor_addr - nc, COLS, 1);
  669.         break;
  670.     }
  671.     return DATA;
  672. }
  673.  
  674. static enum state
  675. ansi_insert_lines(int nn, int ig2 unused)
  676. {
  677.     int rr = cursor_addr / COLS;    /* current row */
  678.     int mr = scroll_bottom - rr;    /* rows left at and below this one */
  679.     int ns;                /* rows that are shifting */
  680.  
  681.     /* If outside of the scrolling region, do nothing */
  682.     if (rr < scroll_top - 1 || rr >= scroll_bottom)
  683.         return DATA;
  684.  
  685.     if (nn < 1)
  686.         nn = 1;
  687.     if (nn > mr)
  688.         nn = mr;
  689.     
  690.     /* Move the victims down */
  691.     ns = mr - nn;
  692.     if (ns)
  693.         ctlr_bcopy(rr * COLS, (rr + nn) * COLS, ns * COLS, 1);
  694.  
  695.     /* Clear the middle of the screen */
  696.     ctlr_aclear(rr * COLS, nn * COLS, 1);
  697.     return DATA;
  698. }
  699.  
  700. static enum state
  701. ansi_delete_lines(int nn, int ig2 unused)
  702. {
  703.     int rr = cursor_addr / COLS;    /* current row */
  704.     int mr = scroll_bottom - rr;    /* max rows that can be deleted */
  705.     int ns;                /* rows that are shifting */
  706.  
  707.     /* If outside of the scrolling region, do nothing */
  708.     if (rr < scroll_top - 1 || rr >= scroll_bottom)
  709.         return DATA;
  710.  
  711.     if (nn < 1)
  712.         nn = 1;
  713.     if (nn > mr)
  714.         nn = mr;
  715.  
  716.     /* Move the surviving rows up */
  717.     ns = mr - nn;
  718.     if (ns)
  719.         ctlr_bcopy((rr + nn) * COLS, rr * COLS, ns * COLS, 1);
  720.  
  721.     /* Clear the rest of the screen */
  722.     ctlr_aclear((rr + ns) * COLS, nn * COLS, 1);
  723.     return DATA;
  724. }
  725.  
  726. static enum state
  727. ansi_delete_chars(int nn, int ig2 unused)
  728. {
  729.     int cc = cursor_addr % COLS;    /* current col */
  730.     int mc = COLS - cc;        /* max chars that can be deleted */
  731.     int ns;                /* chars that are shifting */
  732.  
  733.     if (nn < 1)
  734.         nn = 1;
  735.     if (nn > mc)
  736.         nn = mc;
  737.  
  738.     /* Move the surviving chars left */
  739.     ns = mc - nn;
  740.     if (ns)
  741.         ctlr_bcopy(cursor_addr + nn, cursor_addr, ns, 1);
  742.  
  743.     /* Clear the end of the line */
  744.     ctlr_aclear(cursor_addr + ns, nn, 1);
  745.     return DATA;
  746. }
  747.  
  748. static enum state
  749. ansi_sgr(int ig1 unused, int ig2 unused)
  750. {
  751.     int i;
  752.  
  753.     for (i = 0; i <= nx && i < NN; i++)
  754.         switch (n[i]) {
  755.         case 0:
  756.             gr = 0;
  757.             fg = 0;
  758.             bg = 0;
  759.             break;
  760.         case 1:
  761.             gr |= GR_INTENSIFY;
  762.             break;
  763.         case 4:
  764.             gr |= GR_UNDERLINE;
  765.             break;
  766.         case 5:
  767.             gr |= GR_BLINK;
  768.             break;
  769.         case 7:
  770.             gr |= GR_REVERSE;
  771.             break;
  772.         case 30:
  773.             fg = 0xf0;    /* black */
  774.             break;
  775.         case 31:
  776.             fg = 0xf2;    /* red */
  777.             break;
  778.         case 32:
  779.             fg = 0xf4;    /* green */
  780.             break;
  781.         case 33:
  782.             fg = 0xf6;    /* yellow */
  783.             break;
  784.         case 34:
  785.             fg = 0xf1;    /* blue */
  786.             break;
  787.         case 35:
  788.             fg = 0xf3;    /* megenta */
  789.             break;
  790.         case 36:
  791.             fg = 0xfd;    /* cyan */
  792.             break;
  793.         case 37:
  794.             fg = 0xff;    /* white */
  795.             break;
  796.         case 39:
  797.             fg = 0;    /* default */
  798.             break;
  799.         case 40:
  800.             bg = 0xf0;    /* black */
  801.             break;
  802.         case 41:
  803.             bg = 0xf2;    /* red */
  804.             break;
  805.         case 42:
  806.             bg = 0xf4;    /* green */
  807.             break;
  808.         case 43:
  809.             bg = 0xf6;    /* yellow */
  810.             break;
  811.         case 44:
  812.             bg = 0xf1;    /* blue */
  813.             break;
  814.         case 45:
  815.             bg = 0xf3;    /* megenta */
  816.             break;
  817.         case 46:
  818.             bg = 0xfd;    /* cyan */
  819.             break;
  820.         case 47:
  821.             bg = 0xff;    /* white */
  822.             break;
  823.         case 49:
  824.             bg = 0;    /* default */
  825.             break;
  826.         }
  827.  
  828.     return DATA;
  829. }
  830.  
  831. static enum state
  832. ansi_bell(int ig1 unused, int ig2 unused)
  833. {
  834.     ring_bell();
  835.     return DATA;
  836. }
  837.  
  838. static enum state
  839. ansi_newpage(int ig1 unused, int ig2 unused)
  840. {
  841.     ctlr_clear(False);
  842.     return DATA;
  843. }
  844.  
  845. static enum state
  846. ansi_backspace(int ig1 unused, int ig2 unused)
  847. {
  848.     if (held_wrap) {
  849.         held_wrap = False;
  850.         return DATA;
  851.     }
  852.     if (rev_wraparound_mode) {
  853.         if (cursor_addr > (scroll_top - 1) * COLS)
  854.             cursor_move(cursor_addr - 1);
  855.     } else {
  856.         if (cursor_addr % COLS)
  857.             cursor_move(cursor_addr - 1);
  858.     }
  859.     return DATA;
  860. }
  861.  
  862. static enum state
  863. ansi_cr(int ig1 unused, int ig2 unused)
  864. {
  865.     if (cursor_addr % COLS)
  866.         cursor_move(cursor_addr - (cursor_addr % COLS));
  867.     if (auto_newline_mode)
  868.         (void) ansi_lf(0, 0);
  869.     held_wrap = False;
  870.     return DATA;
  871. }
  872.  
  873. static enum state
  874. ansi_lf(int ig1 unused, int ig2 unused)
  875. {
  876.     int nc = cursor_addr + COLS;
  877.  
  878.     held_wrap = False;
  879.  
  880.     /* If we're below the scrolling region, don't scroll. */
  881.     if ((cursor_addr / COLS) >= scroll_bottom) {
  882.         if (nc < ROWS * COLS)
  883.             cursor_move(nc);
  884.         return DATA;
  885.     }
  886.  
  887.     if (nc < scroll_bottom * COLS)
  888.         cursor_move(nc);
  889.     else
  890.         ansi_scroll();
  891.     return DATA;
  892. }
  893.  
  894. static enum state
  895. ansi_htab(int ig1 unused, int ig2 unused)
  896. {
  897.     int col = cursor_addr % COLS;
  898.     int i;
  899.  
  900.     held_wrap = False;
  901.     if (col == COLS-1)
  902.         return DATA;
  903.     for (i = col+1; i < COLS-1; i++)
  904.         if (tabs[i/8] & 1<<(i%8))
  905.             break;
  906.     cursor_move(cursor_addr - col + i);
  907.     return DATA;
  908. }
  909.  
  910. static enum state
  911. ansi_escape(int ig1 unused, int ig2 unused)
  912. {
  913.     return ESC;
  914. }
  915.  
  916. static enum state
  917. ansi_nop(int ig1 unused, int ig2 unused)
  918. {
  919.     return DATA;
  920. }
  921.  
  922. #define PWRAP { \
  923.     nc = cursor_addr + 1; \
  924.     if (nc < scroll_bottom * COLS) \
  925.         cursor_move(nc); \
  926.     else { \
  927.         if (cursor_addr / COLS >= scroll_bottom) \
  928.             cursor_move(cursor_addr / COLS * COLS); \
  929.         else { \
  930.             ansi_scroll(); \
  931.             cursor_move(nc - COLS); \
  932.         } \
  933.     } \
  934. }
  935.  
  936. static enum state
  937. ansi_printing(int ig1 unused, int ig2 unused)
  938. {
  939.     int nc;
  940.  
  941.     if (held_wrap) {
  942.         PWRAP;
  943.         held_wrap = False;
  944.     }
  945.  
  946.     if (insert_mode)
  947.         (void) ansi_insert_chars(1, 0);
  948.     switch (csd[(once_cset != -1) ? once_cset : cset]) {
  949.         case CSD_LD:    /* line drawing "0" */
  950.         if (ansi_ch >= 0x5f && ansi_ch <= 0x7e)
  951.             ctlr_add(cursor_addr, (unsigned char)(ansi_ch - 0x5f),
  952.                 2);
  953.         else
  954.             ctlr_add(cursor_addr, asc2cg[ansi_ch], 0);
  955.         break;
  956.         case CSD_UK:    /* UK "A" */
  957.         if (ansi_ch == '#')
  958.             ctlr_add(cursor_addr, 0x1e, 2);
  959.         else
  960.             ctlr_add(cursor_addr, asc2cg[ansi_ch], 0);
  961.         break;
  962.         case CSD_US:    /* US "B" */
  963.         ctlr_add(cursor_addr, asc2cg[ansi_ch], 0);
  964.         break;
  965.     }
  966.     once_cset = -1;
  967.     ctlr_add_gr(cursor_addr, gr);
  968.     ctlr_add_fg(cursor_addr, fg);
  969.     ctlr_add_bg(cursor_addr, bg);
  970.     if (wraparound_mode) {
  971.         /*
  972.          * There is a fascinating behavior of xterm which we will
  973.          * attempt to emulate here.  When a character is printed in the
  974.          * last column, the cursor sticks there, rather than wrapping
  975.          * to the next line.  Another printing character will put the
  976.          * cursor in column 2 of the next line.  One cursor-left
  977.          * sequence won't budge it; two will.  Saving and restoring
  978.          * the cursor won't move the cursor, but will cancel all of
  979.          * the above behaviors...
  980.          *
  981.          * In my opinion, very strange, but among other things, 'vi'
  982.          * depends on it!
  983.          */
  984.         if (!((cursor_addr + 1) % COLS)) {
  985.             held_wrap = True;
  986.         } else {
  987.             PWRAP;
  988.         }
  989.     } else {
  990.         if ((cursor_addr % COLS) != (COLS - 1))
  991.             cursor_move(cursor_addr + 1);
  992.     }
  993.     return DATA;
  994. }
  995.  
  996. static enum state
  997. ansi_semicolon(int ig1 unused, int ig2 unused)
  998. {
  999.     if (nx >= NN)
  1000.         return DATA;
  1001.     nx++;
  1002.     return state;
  1003. }
  1004.  
  1005. static enum state
  1006. ansi_digit(int ig1 unused, int ig2 unused)
  1007. {
  1008.     n[nx] = (n[nx] * 10) + (ansi_ch - '0');
  1009.     return state;
  1010. }
  1011.  
  1012. static enum state
  1013. ansi_reverse_index(int ig1 unused, int ig2 unused)
  1014. {
  1015.     int rr = cursor_addr / COLS;    /* current row */
  1016.     int np = (scroll_top - 1) - rr;    /* number of rows in the scrolling
  1017.                        region, above this line */
  1018.     int ns;                /* number of rows to scroll */
  1019.     int nn = 1;            /* number of rows to index */
  1020.  
  1021.     held_wrap = False;
  1022.  
  1023.     /* If the cursor is above the scrolling region, do a simple margined
  1024.        cursor up.  */
  1025.     if (np < 0) {
  1026.         (void) ansi_cursor_up(nn, 0);
  1027.         return DATA;
  1028.     }
  1029.  
  1030.     /* Split the number of lines to scroll into ns */
  1031.     if (nn > np) {
  1032.         ns = nn - np;
  1033.         nn = np;
  1034.     } else
  1035.         ns = 0;
  1036.  
  1037.     /* Move the cursor up without scrolling */
  1038.     if (nn)
  1039.         (void) ansi_cursor_up(nn, 0);
  1040.  
  1041.     /* Insert lines at the top for backward scroll */
  1042.     if (ns)
  1043.         (void) ansi_insert_lines(ns, 0);
  1044.  
  1045.     return DATA;
  1046. }
  1047.  
  1048. static enum state
  1049. ansi_send_attributes(int nn, int ig2 unused)
  1050. {
  1051.     if (!nn)
  1052.         net_sends("\033[?1;2c");
  1053.     return DATA;
  1054. }
  1055.  
  1056. static enum state
  1057. dec_return_terminal_id(int ig1 unused, int ig2 unused)
  1058. {
  1059.     return ansi_send_attributes(0, 0);
  1060. }
  1061.  
  1062. static enum state
  1063. ansi_set_mode(int nn, int ig2 unused)
  1064. {
  1065.     switch (nn) {
  1066.         case 4:
  1067.         insert_mode = 1;
  1068.         break;
  1069.         case 20:
  1070.         auto_newline_mode = 1;
  1071.         break;
  1072.     }
  1073.     return DATA;
  1074. }
  1075.  
  1076. static enum state
  1077. ansi_reset_mode(int nn, int ig2 unused)
  1078. {
  1079.     switch (nn) {
  1080.         case 4:
  1081.         insert_mode = 0;
  1082.         break;
  1083.         case 20:
  1084.         auto_newline_mode = 0;
  1085.         break;
  1086.     }
  1087.     return DATA;
  1088. }
  1089.  
  1090. static enum state
  1091. ansi_status_report(int nn, int ig2 unused)
  1092. {
  1093.     static char cpr[11];
  1094.  
  1095.     switch (nn) {
  1096.         case 5:
  1097.         net_sends("\033[0n");
  1098.         break;
  1099.         case 6:
  1100.         (void) sprintf(cpr, "\033[%d;%dR",
  1101.             (cursor_addr/COLS) + 1, (cursor_addr%COLS) + 1);
  1102.         net_sends(cpr);
  1103.         break;
  1104.     }
  1105.     return DATA;
  1106. }
  1107.  
  1108. static enum state
  1109. ansi_cs_designate(int ig1 unused, int ig2 unused)
  1110. {
  1111.     cs_to_change = strchr(gnnames, ansi_ch) - gnnames;
  1112.     return CSDES;
  1113. }
  1114.  
  1115. static enum state
  1116. ansi_cs_designate2(int ig1 unused, int ig2 unused)
  1117. {
  1118.     csd[cs_to_change] = strchr(csnames, ansi_ch) - csnames;
  1119.     return DATA;
  1120. }
  1121.  
  1122. static enum state
  1123. ansi_select_g0(int ig1 unused, int ig2 unused)
  1124. {
  1125.     cset = CS_G0;
  1126.     return DATA;
  1127. }
  1128.  
  1129. static enum state
  1130. ansi_select_g1(int ig1 unused, int ig2 unused)
  1131. {
  1132.     cset = CS_G1;
  1133.     return DATA;
  1134. }
  1135.  
  1136. static enum state
  1137. ansi_select_g2(int ig1 unused, int ig2 unused)
  1138. {
  1139.     cset = CS_G2;
  1140.     return DATA;
  1141. }
  1142.  
  1143. static enum state
  1144. ansi_select_g3(int ig1 unused, int ig2 unused)
  1145. {
  1146.     cset = CS_G3;
  1147.     return DATA;
  1148. }
  1149.  
  1150. static enum state
  1151. ansi_one_g2(int ig1 unused, int ig2 unused)
  1152. {
  1153.     once_cset = CS_G2;
  1154.     return DATA;
  1155. }
  1156.  
  1157. static enum state
  1158. ansi_one_g3(int ig1 unused, int ig2 unused)
  1159. {
  1160.     once_cset = CS_G3;
  1161.     return DATA;
  1162. }
  1163.  
  1164. static enum state
  1165. ansi_esc3(int ig1 unused, int ig2 unused)
  1166. {
  1167.     return DECP;
  1168. }
  1169.  
  1170. static enum state
  1171. dec_set(int ig1 unused, int ig2 unused)
  1172. {
  1173.     int i;
  1174.  
  1175.     for (i = 0; i <= nx && i < NN; i++)
  1176.         switch (n[i]) {
  1177.             case 1:    /* application cursor keys */
  1178.             appl_cursor = 1;
  1179.             break;
  1180.             case 2:    /* set G0-G3 */
  1181.             csd[0] = csd[1] = csd[2] = csd[3] = CSD_US;
  1182.             break;
  1183.             case 7:    /* wraparound mode */
  1184.             wraparound_mode = 1;
  1185.             break;
  1186.             case 45:    /* reverse-wraparound mode */
  1187.             rev_wraparound_mode = 1;
  1188.             break;
  1189.             case 47:    /* alt buffer */
  1190.             ctlr_altbuffer(True);
  1191.             break;
  1192.         }
  1193.     return DATA;
  1194. }
  1195.  
  1196. static enum state
  1197. dec_reset(int ig1 unused, int ig2 unused)
  1198. {
  1199.     int i;
  1200.  
  1201.     for (i = 0; i <= nx && i < NN; i++)
  1202.         switch (n[i]) {
  1203.             case 1:    /* normal cursor keys */
  1204.             appl_cursor = 0;
  1205.             break;
  1206.             case 7:    /* no wraparound mode */
  1207.             wraparound_mode = 0;
  1208.             break;
  1209.             case 45:    /* no reverse-wraparound mode */
  1210.             rev_wraparound_mode = 0;
  1211.             break;
  1212.             case 47:    /* alt buffer */
  1213.             ctlr_altbuffer(False);
  1214.             break;
  1215.         }
  1216.     return DATA;
  1217. }
  1218.  
  1219. static enum state
  1220. dec_save(int ig1 unused, int ig2 unused)
  1221. {
  1222.     int i;
  1223.  
  1224.     for (i = 0; i <= nx && i < NN; i++)
  1225.         switch (n[i]) {
  1226.             case 1:    /* application cursor keys */
  1227.             saved_appl_cursor = appl_cursor;
  1228.             break;
  1229.             case 7:    /* wraparound mode */
  1230.             saved_wraparound_mode = wraparound_mode;
  1231.             break;
  1232.             case 45:    /* reverse-wraparound mode */
  1233.             saved_rev_wraparound_mode = rev_wraparound_mode;
  1234.             break;
  1235.             case 47:    /* alt buffer */
  1236.             saved_altbuffer = is_altbuffer;
  1237.             break;
  1238.         }
  1239.     return DATA;
  1240. }
  1241.  
  1242. static enum state
  1243. dec_restore(int ig1 unused, int ig2 unused)
  1244. {
  1245.     int i;
  1246.  
  1247.     for (i = 0; i <= nx && i < NN; i++)
  1248.         switch (n[i]) {
  1249.             case 1:    /* application cursor keys */
  1250.             appl_cursor = saved_appl_cursor;
  1251.             break;
  1252.             case 7:    /* wraparound mode */
  1253.             wraparound_mode = saved_wraparound_mode;
  1254.             break;
  1255.             case 45:    /* reverse-wraparound mode */
  1256.             rev_wraparound_mode = saved_rev_wraparound_mode;
  1257.             break;
  1258.             case 47:    /* alt buffer */
  1259.             ctlr_altbuffer(saved_altbuffer);
  1260.             break;
  1261.         }
  1262.     return DATA;
  1263. }
  1264.  
  1265. static enum state
  1266. dec_scrolling_region(int top, int bottom)
  1267. {
  1268.     if (top < 1)
  1269.         top = 1;
  1270.     if (bottom > ROWS)
  1271.         bottom = ROWS;
  1272.     if (top <= bottom && (top > 1 || bottom < ROWS)) {
  1273.         scroll_top = top;
  1274.         scroll_bottom = bottom;
  1275.         cursor_move(0);
  1276.     } else {
  1277.         scroll_top = 1;
  1278.         scroll_bottom = ROWS;
  1279.     }
  1280.     return DATA;
  1281. }
  1282.  
  1283. static enum state
  1284. xterm_text_mode(int ig1 unused, int ig2 unused)
  1285. {
  1286.     nx = 0;
  1287.     n[0] = 0;
  1288.     return TEXT;
  1289. }
  1290.  
  1291. static enum state
  1292. xterm_text_semicolon(int ig1 unused, int ig2 unused)
  1293. {
  1294.     tx = 0;
  1295.     return TEXT2;
  1296. }
  1297.  
  1298. static enum state
  1299. xterm_text(int ig1 unused, int ig2 unused)
  1300. {
  1301.     if (tx < NT)
  1302.         text[tx++] = ansi_ch;
  1303.     return state;
  1304. }
  1305.  
  1306. static enum state
  1307. xterm_text_do(int ig1 unused, int ig2 unused)
  1308. {
  1309. #if defined(X3270_DISPLAY) /*[*/
  1310.     text[tx] = '\0';
  1311.  
  1312.     switch (n[0]) {
  1313.         case 0:    /* icon name and window title */
  1314.         XtVaSetValues(toplevel, XtNiconName, text, NULL);
  1315.         XtVaSetValues(toplevel, XtNtitle, text, NULL);
  1316.         break;
  1317.         case 1:    /* icon name */
  1318.         XtVaSetValues(toplevel, XtNiconName, text, NULL);
  1319.         break;
  1320.         case 2:    /* window_title */
  1321.         XtVaSetValues(toplevel, XtNtitle, text, NULL);
  1322.         break;
  1323.         case 50:    /* font */
  1324.         screen_newfont(text, False);
  1325.         break;
  1326.     }
  1327. #endif /*]*/
  1328.     return DATA;
  1329. }
  1330.  
  1331. static enum state
  1332. ansi_htab_set(int ig1 unused, int ig2 unused)
  1333. {
  1334.     register int col = cursor_addr % COLS;
  1335.  
  1336.     tabs[col/8] |= 1<<(col%8);
  1337.     return DATA;
  1338. }
  1339.  
  1340. static enum state
  1341. ansi_htab_clear(int nn, int ig2 unused)
  1342. {
  1343.     register int col, i;
  1344.  
  1345.     switch (nn) {
  1346.         case 0:
  1347.         col = cursor_addr % COLS;
  1348.         tabs[col/8] &= ~(1<<(col%8));
  1349.         break;
  1350.         case 3:
  1351.         for (i = 0; i < (COLS+7)/8; i++)
  1352.             tabs[i] = 0;
  1353.         break;
  1354.     }
  1355.     return DATA;
  1356. }
  1357.  
  1358. /*
  1359.  * Scroll the screen or the scrolling region.
  1360.  */
  1361. static void
  1362. ansi_scroll(void)
  1363. {
  1364.     held_wrap = False;
  1365.  
  1366.     /* Save the top line */
  1367.     if (scroll_top == 1 && scroll_bottom == ROWS) {
  1368.         if (!is_altbuffer)
  1369.             scroll_save(1, False);
  1370.         ctlr_scroll();
  1371.         return;
  1372.     }
  1373.  
  1374.     /* Scroll all but the last line up */
  1375.     if (scroll_bottom > scroll_top)
  1376.         ctlr_bcopy(scroll_top * COLS,
  1377.             (scroll_top - 1) * COLS,
  1378.             (scroll_bottom - scroll_top) * COLS,
  1379.             1);
  1380.  
  1381.     /* Clear the last line */
  1382.     ctlr_aclear((scroll_bottom - 1) * COLS, COLS, 1);
  1383. }
  1384.  
  1385. /* Callback for when we enter ANSI mode. */
  1386. static void
  1387. ansi_in3270(Boolean in3270)
  1388. {
  1389.     if (!in3270)
  1390.         (void) ansi_reset(0, 0);
  1391. }
  1392.  
  1393.  
  1394. /*
  1395.  * External entry points
  1396.  */
  1397.  
  1398. void
  1399. ansi_init(void)
  1400. {
  1401.     register_schange(ST_3270_MODE, ansi_in3270);
  1402. }
  1403.  
  1404. void
  1405. ansi_process(unsigned int c)
  1406. {
  1407.     c &= 0xff;
  1408.     ansi_ch = c;
  1409.  
  1410.     scroll_to_bottom();
  1411.  
  1412. #if defined(X3270_TRACE) /*[*/
  1413.     if (toggled(SCREEN_TRACE))
  1414.         trace_char((char)c);
  1415. #endif /*]*/
  1416.  
  1417.     state = (*ansi_fn[st[(int)state][c]])(n[0], n[1]);
  1418. }
  1419.  
  1420. void
  1421. ansi_send_up(void)
  1422. {
  1423.     if (appl_cursor)
  1424.         net_sends("\033OA");
  1425.     else
  1426.         net_sends("\033[A");
  1427. }
  1428.  
  1429. void
  1430. ansi_send_down(void)
  1431. {
  1432.     if (appl_cursor)
  1433.         net_sends("\033OB");
  1434.     else
  1435.         net_sends("\033[B");
  1436. }
  1437.  
  1438. void
  1439. ansi_send_right(void)
  1440. {
  1441.     if (appl_cursor)
  1442.         net_sends("\033OC");
  1443.     else
  1444.         net_sends("\033[C");
  1445. }
  1446.  
  1447. void
  1448. ansi_send_left(void)
  1449. {
  1450.     if (appl_cursor)
  1451.         net_sends("\033OD");
  1452.     else
  1453.         net_sends("\033[D");
  1454. }
  1455.  
  1456. void
  1457. ansi_send_home(void)
  1458. {
  1459.     net_sends("\033[H");
  1460. }
  1461.  
  1462. void
  1463. ansi_send_clear(void)
  1464. {
  1465.     net_sends("\033[2K");
  1466. }
  1467.  
  1468. void
  1469. ansi_send_pf(int nn)
  1470. {
  1471.     static char fn_buf[6];
  1472.     static int code[] = {
  1473.         /*
  1474.          * F1 through F12 are VT220 codes. (Note the discontinuity --
  1475.          * \E[16~ is missing)
  1476.          */
  1477.         11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 23, 24,
  1478.         /*
  1479.          * F13 through F20 are defined for xterm.
  1480.          */
  1481.         25, 26, 28, 29, 31, 32, 33, 34,
  1482.         /*
  1483.          * F21 through F24 are x3270 extensions.
  1484.          */
  1485.         35, 36, 37, 38
  1486.     };
  1487.  
  1488.     if (nn < 1 || nn > sizeof(code)/sizeof(code[0]))
  1489.         return;
  1490.     (void) sprintf(fn_buf, "\033[%d~", code[nn-1]);
  1491.     net_sends(fn_buf);
  1492. }
  1493.  
  1494. void
  1495. ansi_send_pa(int nn)
  1496. {
  1497.     static char fn_buf[4];
  1498.     static char code[4] = { 'P', 'Q', 'R', 'S' };
  1499.  
  1500.     if (nn < 1 || nn > 4)
  1501.         return;
  1502.     (void) sprintf(fn_buf, "\033O%c", code[nn-1]);
  1503.     net_sends(fn_buf);
  1504. }
  1505.  
  1506. void
  1507. toggle_lineWrap(struct toggle *t unused, enum toggle_type type unused)
  1508. {
  1509.     if (toggled(LINE_WRAP))
  1510.         wraparound_mode = 1;
  1511.     else
  1512.         wraparound_mode = 0;
  1513. }
  1514.  
  1515. #endif /*]*/
  1516.